This tutorial will create a Modeler LScript that will create a helix-shaped curve.
|
|
First, we begin by creating the script shell that all Modeler LScripts must use. The shell is the name main following by the body of thefunction.
|
|
main { ... } |
|
The first thing we need to do in our function is switch the script into "mesh edit" mode by making a call to the LScript function editbegin() . It is inthis mode that we modify Modeler's mesh data, by adding, deleting or moving things like points, polygons and curves. If we attempt to perform any of these operations without being in "mesh edit" mode, LScript will generate an error, and terminate our script.
|
|
Each call to editbegin() should be matched by a terminating callto editend() . Until you invoke editend() with a true flag, your mesh edit operations will not be applied the the active Modeler layers. This allows you to abort any changes you may have made to existing mesh data by calling editend() with a false flag.
|
|
main { editbegin(); ... editend(); } |
|
The astute reader will notice that we didn't provide a flag parameter to theeditend() call in the code fragment above. The reason for this isthat this parameter is optional, and the default value used if the parameter is not provided is true .
|
|
Now that we are in "mesh edit" mode, we can begin adding data to Modeler's active foreground layer(s). Please note that, in this tutorial, we are assume that the script user has already selected the layer or layers into which they wish this data to be placed. In the next tutorial, we will set layers for ourselves as the script performs its processing.
|
|
In order to create a helix curve, we must decide upon the value of a number of variables that will be used to contruct the coil. These variables are:
|
|
|
|
Before we determine these factors, however, we know that we will probably have to perform a loop within our script to process each successive point that is added to the coil. The loop control that we will use will be a for() loop. This type of loop control is quite similar to thatused by the C language, and it contains all of the looping conditions in a single statement.
|
|
main { editbegin(); ... for(x = 2;x <= TOTALPOINTS;x++) { ... } ... editend(); } |
|
Notice in the above code fragment that we have hard-coded the initial value of our loop-counter variable x to be "2". The reason for this will be cleareras the body of our script evolves.
|
|
Now, we must take a moment and determine the shaping factors of our curve. In our script, we want the helix coil to curve about the Y axis a full 360 degrees from its starting point. To create a smooth curve, we will place points along the coil every 30 degrees. By dividing 360 by 30, we find that we will need a total of 12 points on our helix. As we construct our helix, we will cause it to rise along the Y axis by 10 cm (or .1 meters) at each step. Our radius from the center of the coil will be .5 meters.
|
|
Let's look at the values that we will be using to contruct this helix curve:
|
number of points | ... | 12 |
number of degrees between each point | ... | 30 |
the increment in positive-Y units | ... | 10 cm (or .1 meters) |
the radius of each point from the center of the coil | ... | 50 cm (or .5 meters) |
where the initial point will be placed | ... | <.5,0,0> |
Now, we can convert these values into script code.
|
|
First, we will add macros to represent the number of points our helix coil will contain, the number of degrees in each step, and the increment along the Y axis. This is placed at the top of our script code.
|
|
@define TOTALPOINTS 12 @define DEGSTEP 30 @define HEIGHTINCR .1 main { editbegin(); ... for(x = 2;x <= TOTALPOINTS;x++) { ... } ... editend(); } |
|
We use macros not only to make the script code more readable, but more importantly to help localize changes to our script code. In our current script, we only use the point count and height increment in one location, so it would be easy enough to change it if we wished. However, in larger, more-complex scripts we might use the point-count value in many different locations (like the degree step is used in our script). If we were required to change all these locations each time we wanted to change the number of points generated, we would not only have a lot more work on our hands, but there is an increasing possibility that we could miss some locations or even type in the wrong number at one of them! By using macros, we merely change the value in one location, and all instances of the macro name are updated accordingly.
|
|
Next, we will create a variable to hold the current point position. We then use that point location to create an actual point within Modeler by calling the addpoint() LScript function. The return value of this function isan identifier for the newly-created point, and is assigned to the first element of our point id array. We use an array to remember all the point ids returned to us by Modeler as we create new points. We then use all these point ids to create a new curve at the end of our script:
|
|
@define TOTALPOINTS 12 @define DEGSTEP 30 @define HEIGHTINCR .1 main { editbegin(); thepoint = <.5,0,0>; pnt[1] = addpoint(thepoint); for(x = 2;x <= TOTALPOINTS;x++) { ... } ... editend(); } |
|
From the code fragment above, you can now see why the loop counter begins at "2" instead of "1". We have already assigned a value to the first element in our array, our anchor point, and need to continue assigning with the second and subsequent elements. We accomplish this within our for() loop control.
|
|
Two more variables are used for the calculations within our for() loop. These values hold the radius and absolute degrees of the current point. Because these values change or must be caculated during the course of the script's execution, they cannot be placed into macros:
|
|
@define TOTALPOINTS 12 @define DEGSTEP 30 @define HEIGHTINCR .1 main { editbegin(); thepoint = <.5,0,0>; pnt[1] = addpoint(thepoint); radius = sqrt((thepoint.x * thepoint.x) + (thepoint.z * thepoint.z)); degrees = DEGSTEP; for(x = 2;x <= TOTALPOINTS;x++) { ... } ... editend(); } |
|
The radius calculation seems slightly useless because we have already determined that our radius will be .5 meters from the center. However, if at some later time find yourself dealing with an unknown initial point value (perhaps you've allowed the user to place the initial point), then you will not have a clear idea of the radius. The calculation used above will always determine the correct radius, regardless of where the point is initially placed.
|
|
At this point in our script, we have our first point along the helix coil. This first point is our anchor. Now, within the for() loop, we will place the remaining11 points into Modeler. The first thing we do for each successive point is move it along the positive-Y axis by our pre-defined increment value:
|
|
@define TOTALPOINTS 12 @define DEGSTEP 30 @define HEIGHTINCR .1 main { editbegin(); thepoint = <.5,0,0>; pnt[1] = addpoint(thepoint); radius = sqrt((thepoint.x * thepoint.x) + (thepoint.z * thepoint.z)); degrees = DEGSTEP; for(x = 2;x <= TOTALPOINTS;x++) { thepoint.y += HEIGHTINCR; ... } ... editend(); } |
|
Next, we perform some trigonometric calculations to determine where the new point will lie along the helix curve:
|
|
@define TOTALPOINTS 12 @define DEGSTEP 30 @define HEIGHTINCR .1 main { editbegin(); thepoint = <.5,0,0>; pnt[1] = addpoint(thepoint); radius = sqrt((thepoint.x * thepoint.x) + (thepoint.z * thepoint.z)); degrees = DEGSTEP; for(x = 2;x <= TOTALPOINTS;x++) { thepoint.y += HEIGHTINCR; thepoint.x = radius * cos(rad(degrees)); thepoint.z = radius * sin(rad(degrees)); ... } ... editend(); } |
|
We then add this new point into Modeler's mesh data, and increment the sweep around the coil by the degree value:
|
|
@define TOTALPOINTS 12 @define DEGSTEP 30 @define HEIGHTINCR .1 main { editbegin(); thepoint = <.5,0,0>; pnt[1] = addpoint(thepoint); radius = sqrt((thepoint.x * thepoint.x) + (thepoint.z * thepoint.z)); degrees = DEGSTEP; for(x = 2;x <= TOTALPOINTS;x++) { thepoint.y += HEIGHTINCR; thepoint.x = radius * cos(rad(degrees)); thepoint.z = radius * sin(rad(degrees)); pnt[x] = addpoint(thepoint); degrees += DEGSTEP; } ... editend(); } |
|
Finally, we add a call to LScript's addcurve() , passing to itour array of point identifiers. Modeler will then create our helix curve from the points we just created:
|
|
@define TOTALPOINTS 12 @define DEGSTEP 30 @define HEIGHTINCR .1 main { editbegin(); thepoint = <.5,0,0>; pnt[1] = addpoint(thepoint); radius = sqrt((thepoint.x * thepoint.x) + (thepoint.z * thepoint.z)); degrees = DEGSTEP; for(x = 2;x <= TOTALPOINTS;x++) { thepoint.y += HEIGHTINCR; thepoint.x = radius * cos(rad(degrees)); thepoint.z = radius * sin(rad(degrees)); pnt[x] = addpoint(thepoint); degrees += DEGSTEP; } addcurve(pnt); editend(); } |